namespace SimpleWebServices.Configuration
{
    using System.IO;
    using System.Web;
    using System.Xml.XPath;
    using Moq;
    using SimpleWebServices;
    using SimpleWebServices.Data;
    using SimpleWebServices.Web;
    using Xunit;

    public sealed class XmlXmlDataSettingFacts
    {
        [Fact]
        public void typedef()
        {
            Assert.True(new ObjectExpectations<XmlDataSetting>()
                .DerivesFrom<object>()
                .IsConcreteClass()
                .IsSealed()
                .HasDefaultConstructor()
                .XmlRoot("xml")
                .Result);
        }

        [Fact]
        public void ctor()
        {
            Assert.NotNull(new XmlDataSetting());
        }

        [Fact]
        public void deserialize()
        {
            XmlDataSetting actual = @"<xml enabled='true' path='~\Data' />".Deserialize<XmlDataSetting>();

            Assert.NotNull(actual);

            Assert.True(actual.Enabled.Value);
            Assert.Equal<string>(@"~\Data", actual.Path);
        }

        [Fact]
        public void deserializeEmpty()
        {
            XmlDataSetting actual = "<xml />".Deserialize<XmlDataSetting>();

            Assert.NotNull(actual);

            Assert.False(actual.Enabled.HasValue);
            Assert.Null(actual.Path);
        }

        [Fact]
        public void serialize()
        {
            XmlDataSetting obj = new XmlDataSetting
            {
                Enabled = true,
                Path = @"~\Data"
            };

            XPathNavigator navigator = obj.Serialize().CreateNavigator();

            Assert.True((bool)navigator.Evaluate(@"1=count(/xml[@enabled='true'][@path='~\Data'])"));
        }

        [Fact]
        public void prop_Enabled()
        {
            Assert.True(new PropertyExpectations(typeof(XmlDataSetting).GetProperty("Enabled"))
                .XmlIgnore()
                .IsAutoProperty<bool?>()
                .Result);
        }

        [Fact]
        public void prop_EnabledValue()
        {
            Assert.True(new PropertyExpectations(typeof(XmlDataSetting).GetProperty("EnabledValue"))
                .XmlAttribute("enabled")
                .IsAutoProperty<string>()
                .Result);
        }

        [Fact]
        public void prop_Path()
        {
            Assert.True(new PropertyExpectations(typeof(XmlDataSetting).GetProperty("Path"))
                .XmlAttribute("path")
                .IsAutoProperty<string>()
                .Result);
        }

        [Fact]
        public void op_Upsert_whenDisabled()
        {
            FakeRepository.Clear();

            try
            {
                FakeRepository.Register();

                XmlDataSetting obj = new XmlDataSetting
                {
                    Enabled = false
                };
            }
            finally
            {
                FakeRepository.Reset();
            }
        }

        [Fact]
        public void op_Upsert_whenEnabledWithEmptyPath()
        {
            FakeRepository.Clear();

            try
            {
                FakeRepository.Register();

                XmlDataSetting obj = new XmlDataSetting
                {
                    Enabled = true,
                    Path = string.Empty
                };
            }
            finally
            {
                FakeRepository.Reset();
            }
        }

        [Fact]
        public void op_Upsert_whenEnabled()
        {
            FakeRepository.Clear();

            try
            {
                FakeRepository tests = FakeRepository.Register<TestRecord>();

                XmlDataSetting obj = new XmlDataSetting
                {
                    Enabled = true,
                    Path = @"Data\Record.Test.object.xml"
                };

                obj.Upsert();

                Assert.True((bool)tests.Xml.CreateNavigator().Evaluate("2 = count(//test[@value])"));
            }
            finally
            {
                FakeRepository.Reset();
            }
        }

        [Fact]
        public void op_Upsert_whenEnabledWithMappedPath()
        {
            FakeRepository.Clear();

            try
            {
                FakeRepository tests = FakeRepository.Register<TestRecord>();

                string path = @"Data\Record.Test.object.xml";

                var mock = new Mock<HttpContextBase>();
                mock.Setup<string>(x => x.Server.MapPath(It.IsAny<string>())).Returns(new FileInfo(path).FullName).Verifiable();
                HttpContextFactory.Mock = mock.Object;

                XmlDataSetting obj = new XmlDataSetting
                {
                    Enabled = true,
                    Path = "~" + path
                };

                obj.Upsert();

                Assert.True((bool)tests.Xml.CreateNavigator().Evaluate("2 = count(//test[@value])"));

                mock.VerifyAll();
            }
            finally
            {
                FakeRepository.Reset();
                HttpContextFactory.Reset();
            }
        }
    }
}